﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using MgSoft.Import.Excel.Model;
using Autofac;
using MgSoft.DependenceInjection.Autofac;
using MgSoft.Configure;
using MgSoft.Log.MgSerilog.Autofac;

namespace MgSoft.Import.Excel
{
    public abstract class ExcelController : Controller, IExcelController
    {
        /// <summary>
        /// Excel组件集
        /// </summary>
        public List<IExcelComponent> Components { get; protected set; }
        /// <summary>
        /// 组件容器
        /// </summary>
        protected IContainer importContainer { get; private set; }
        /// <summary>
        /// 组件构建前事件
        /// </summary>
        public Action<ContainerBuilder> BeforeCompomentsBuilderAction { get; set; }

        public virtual IExcelComponent GetComponentByName(string componentName)
        {
            var result = Components.Where(p => p.Name == componentName).FirstOrDefault();
            if (result == null)
            {
                throw new MgException("找不到组件");
            }
            return result;
        }

        /// <summary>
        /// 获取所有的Excel导入策略
        /// </summary>
        /// <returns></returns>
        public virtual List<ExcelTaskTypeInfo> GetAllExcelTaskType()
        {
            try
            {
                List<ExcelTaskTypeInfo> result = new List<ExcelTaskTypeInfo>();
                foreach (var component in Components)
                {
                    var excelTaskType = component.GetAllExcelTaskType(importContainer);
                    result.AddRange(excelTaskType);
                }
                return result;
            }
            catch (Exception ex)
            {
                throw ex.InnerException is null ? ex : ex.InnerException;
            }
        }

        /// <summary>
        /// 获取组件方案下所有的导入Excel的策略
        /// </summary>
        /// <returns></returns>
        public virtual List<ExcelTaskTypeInfo> GetAllExcelTaskType(IExcelComponent excelComponent)
        {
            try
            {
                var result = excelComponent.GetAllExcelTaskType(importContainer);
                return result;
            }
            catch (Exception ex)
            {
                throw ex.InnerException is null ? ex : ex.InnerException;
            }
        }

        /// <summary>
        /// 获取组件方案下所有的导入Excel的策略
        /// </summary>
        /// <returns></returns>
        public virtual List<ExcelTaskTypeInfo> GetAllExcelTaskType(string excelComponentName)
        {
            try
            {
                var excelComponent = GetComponentByName(excelComponentName);

                var result = excelComponent.GetAllExcelTaskType(importContainer);
                return result;
            }
            catch (Exception ex)
            {
                throw ex.InnerException is null ? ex : ex.InnerException;
            }
        }


        /// <summary>
        /// 初始化并对数据进行校验
        /// </summary>
        /// <param name="componentName"></param>
        /// <param name="fileExcelTaskTypes"></param>
        /// <returns></returns>
        public AggregateExcelMessage InitAndCheck(string componentName, List<FileExcelTaskTypeInfo> fileExcelTaskTypes, AggregateExcelMessage inAggregateExcelMessage)
        {
            var component = this.GetComponentByName(componentName);
            var excelScheme = component.GetScheme(importContainer);
            return excelScheme.InitAndCheck(fileExcelTaskTypes, inAggregateExcelMessage);

        }

        /// <summary>
        /// 导入数据
        /// </summary>
        /// <param name="componentName"></param>
        /// <param name="fileExcelTaskTypes"></param>
        /// <returns></returns>
        public AggregateExcelMessage Import(string componentName, List<FileExcelTaskTypeInfo> fileExcelTaskTypes, AggregateExcelMessage aggregateExcelMessage)
        {
            var component = this.GetComponentByName(componentName);
            var excelScheme = component.GetScheme(importContainer);
            return excelScheme.Import(fileExcelTaskTypes, aggregateExcelMessage);
        }

        public void WriteErrorToExcel(string componentName, FileExcelTaskTypeInfo fileExcelTaskType, AggregateExcelMessage aggregateExcelMessage, string folderPath)
        {
            var component = this.GetComponentByName(componentName);
            var excelScheme = component.GetScheme(importContainer);
            excelScheme.WriteErrorToExcel(fileExcelTaskType, aggregateExcelMessage, folderPath);
        }

        /// <summary>
        /// 构建Excel组件容器
        /// </summary>
        /// <param name="files"></param>
        /// <returns>一个组件一个容器，后续方便进行单元测试</returns>
        protected virtual List<IExcelComponent> BuilderImportContainer(List<IExcelComponent> excelComponents)
        {
            ContainerBuilder builder = new ContainerBuilder();

            registerComponent(builder, excelComponents);
            registerAllType(builder, excelComponents);
            registerMemoryConfig(builder);
            registerLogger(builder);

            if (BeforeCompomentsBuilderAction != null) BeforeCompomentsBuilderAction(builder);
            excelComponents.ForEach(p => p.BeforeBuilder(builder));
            importContainer = builder.Build();
            excelComponents.ForEach(p => p.AfterBuilder(importContainer));

            return excelComponents;
        }

        /// <summary>
        /// 把组件自已注册到容器中
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="result"></param>
        protected virtual void registerComponent(ContainerBuilder builder, List<IExcelComponent> result)
        {
            result.ForEach(p =>
            {
                builder.RegisterType(p.GetType()).OnActivating(t => t.ReplaceInstance(p));
            });
        }

        protected virtual void registerAllType(ContainerBuilder containerBuilder, List<IExcelComponent> components)
        {
            foreach (var component in components)
            {
                component.Register(containerBuilder);
                RegisterAssemblyType.Register(component.GetType().Assembly, containerBuilder);
            }
        }

        /// <summary>
        /// 使用内存配置
        /// </summary>
        /// <param name="builder"></param>
        protected virtual void registerMemoryConfig(ContainerBuilder builder)
        {
            builder.RegisterType<MemoryConfigService>().As<IConfigService>().SingleInstance();
        }


        protected virtual void registerLogger(ContainerBuilder builder)
        {
            new LogMgSerilogComponent().Register(builder);
        }
    }
}
